////////////////////////////////////////////////////////////////////
///
///   EmailMessage.h - Mime message parser
///
///   Copyright (C) 2007 ScalingWeb.com
///   All rights reserved. 
/// 
///   Authors: Yuriy Soroka <ysoroka@scalingweb.com>
///	       Anton Fedoruk <afedoruk@scalingweb.com>
///
/// 
///////////////////////////////////////////////////////////////////


#ifndef __EmailMessage_h__
#define __EmailMessage_h__

#include <QStringList>
#include <QByteArray>
#include <QBuffer>
#include <QVector>
#include "JInputStream.h"
#include "JBufferString.h"
#include "JBufferedInputStream.h"

const int MaxLineSize = 65536;

///
///  MailHeader 
///

class MailHeader
{
public:

	 MailHeader();
	 virtual ~MailHeader();

	 /// 
	 ///  Getter methods return header message parameters, 
	 ///  such as subject, to, from, priority etc.
	 virtual const QString& getMessageId() const;

	 virtual const QStringList& getTo() const;

 	 virtual const QStringList& getCc() const;

 	 virtual const QStringList& getBcc() const;

	 virtual const QString& getFrom() const;

	 virtual const QString& getSubject() const;	 

	 virtual long getDate() const;	 

	 virtual uint getPriority() const;

	 virtual void clear();

protected:

	QString messageId_;
	QStringList recipients_;
	QStringList cc_;
	QStringList bcc_;
	QString sender_;
	QString subject_;
	long date_;
	uint priority_;
};

///
///	EmailMessage helps with parsing raw bytes 
/// email messages, and extracting all necessary information
/// (fast parsing)
///
class EmailMessage 
	: public MailHeader
{
public:

	EmailMessage();
	virtual ~EmailMessage();

	///
	/// Opens email message from InputStream
	///
	bool open(JInputStream *stream);

	///
	///	@return mime type of a message
	///
	const QByteArray& contentType();

	///
	///	@return message text
	///
	const QString& text();

	///
	/// @return email message size
	///

	size_t size() const;

	/// Attachments

	///
	/// @return true if email has attachments, otherwise false
	///
	bool hasAttachments() const ;

	///
	///  @return list of filenames of available attachments.
	///
	QStringList attachments();

	///
	///	Reads attachment specified with file name
	/// @param name - Attachment file name
	/// @param container to place contents of an attachment or empty byte array if 
	///			no such file exists.
	///
	bool readAttachment(const QString& name, QByteArray& contents, QByteArray& contentType);

	///
	/// Says delete or not stream in destructor
	void setDeleteStream( bool isDelete = true );

	///
	/// if bOnly equals true 
	void parseHeaderOnly( bool bOnly = true );

	static bool isHexString( const QByteArray &hex );

	// Decodes encoded text and returns unicode string
	static QString decodeNonAsciiText( JBufferString &text );
	static int encode( QByteArray &text, const JBufferString &encoding, bool bShortForm = false );

protected:

	// Type of content body
	enum contenttype
	{
		e_text		= 0xA,
		e_multipart	= 0xF,
		e_other		= 0xD
	} 
	enumConType_;

	void initParams();
	void init();

	void processParameter( JBufferString &paramText );
	bool parseMimeBody();

	bool compareNoCase( const char *ca1, const char *ca2 );

	void parseContentType( JBufferString &paramString );
	void parseFrom( JBufferString &paramString );
	void parseDate( JBufferString &paramString );
	void parseContentDisp( JBufferString &paramString, bool &bMulti, 
		bool bTextEmpty, int boundaryPos, int &nameCounter );
	void parseAddrList( QStringList &addrList, JBufferString &line );
	void getExt( const QByteArray &contentType, QByteArray &extension );

	void addAttachment();

	bool isUUencoded( JBufferString &line, QByteArray &filename );
	void uudecode( bool extract, QByteArray &outData );

	JBufferedInputStream< JInputStream > readline_;
	JInputStream *emailStream_;

	// Represents one attachment
	struct AttachmentItem
	{
		AttachmentItem() {}
		AttachmentItem( QString Name, qint64 Pos )
		{
			AttachmentName = Name;
			FilePos = Pos;
		}

		QString AttachmentName;
		qint64 FilePos;
	};

	QVector< AttachmentItem > attachments_;

	QString text_;

	QByteArray boundary_;
	QByteArray encoding_;
	QByteArray retContentType_;
	QByteArray contentType_;
	QByteArray charset_;
	qint64 boundaryPos_;
	bool bAutoDelete_;
	bool bParseHeaderOnly_;

	QString attachName_;
	qint64 attachPos_;
	bool bAddAttachment_;

};

#endif // __EmailMessage_h__

